#include "UniformBuffer.hpp"

namespace gl
{

UniformBuffer::UniformBuffer() :
	mUbo(0),
	mStoredByteSize(0)
{
	glGenBuffers(1, &mUbo);
}

bool UniformBuffer::setData(void *data, unsigned int size, StoreType storeType)
{
	glBindBuffer(GL_UNIFORM_BUFFER, mUbo);

	unsigned int glStoreType = GL_STATIC_DRAW;
	switch(storeType)
	{
		case StoreType::STREAM:
			glStoreType = GL_STREAM_DRAW;
			break;
		case StoreType::DYNAMIC:
			glStoreType = GL_DYNAMIC_DRAW;
			break;
	}

	glBufferData(GL_UNIFORM_BUFFER, size, data, glStoreType);

	GLenum glError = glGetError();
	switch(glError)
	{
		case GL_OUT_OF_MEMORY:
			// Unable to allocate a buffer of vertices.size() * sizeof(float) bytes.
			glBindBuffer(GL_UNIFORM_BUFFER, 0);
			return false;
	}

	glBindBuffer(GL_UNIFORM_BUFFER, 0);
	mStoredByteSize = size;
	return true;
}

bool UniformBuffer::setSubData(void *data, unsigned int size, unsigned int offset)
{
	glBindBuffer(GL_UNIFORM_BUFFER, mUbo);
	glBufferSubData(GL_UNIFORM_BUFFER, offset, size, data);

	GLenum glError = glGetError();
	switch(glError)
	{
		case GL_INVALID_VALUE:
			// Sub data exceeds glBufferData allocated size.
			// Use glBufferData (setData) instead to reallocate buffer.
			glBindBuffer(GL_UNIFORM_BUFFER, 0);
			return false;
	}

	glBindBuffer(GL_UNIFORM_BUFFER, 0);
	return true;
}

UniformBuffer::~UniformBuffer()
{
	glDeleteBuffers(1, &mUbo);
}

}